<template>
	<view class="cascader-select-panel">
		<u-checkbox-group :active-color="activeColor">
			<u-empty v-if="(tabDataList || []).length <= 0" text="暂无数据" />
			<view v-else class="tabs">
				<view class="tabs_wrap">
					<view class="tabs_nav">
						<view class="tab" v-for="(tabData, index) in tabDataList" :key="tabData.id"
							:class="{'active': index === activePanel, 'unselected': tabData.value == null}"
							@click="changeTab(index)">
							<view class="tab_text">
								<text class="tab-item">{{getTabItemTitle(tabData) || '请选择'}}</text>
							</view>
						</view>
					</view>
				</view>
				<view class="tabs_content">
					<view class="tab-content-item">
						<u-empty v-if="getTabContentList(currentTabData.index).length <= 0" text="暂无数据" />
						<view class="cell-item u-cell u-border-bottom" v-else
							v-for="(data, i) in getTabContentList(currentTabData.index)" :key="data[finalProps.value]"
							@click="onClickNode(data)">
							<view class="u-cell_title" style="min-width:80%;">
								<u-checkbox v-if="!finalProps.showCheckbox || data[finalProps.showCheckbox]"
									:name="data[finalProps.value]" :value="isChecked(data)" @change="onSelectChange"
									:disabled="calcItemDisabled(data)">
									{{ data[finalProps.text] }}
								</u-checkbox>
								<text v-else
									:style="{color: (finalProps.showCheckbox&& !data[finalProps.showCheckbox] && selectPathId.indexOf(data[finalProps.value]) !== -1) ? '#fa3534' : undefined}">{{ data[finalProps.text] }}</text>
							</view>
							<view class="u-cell__value">
								<u-badge v-if="hasChild(data) && getChildSelectCount(data)" type="error"
									:count="getChildSelectCount(data)" :absolute="false"></u-badge>
							</view>
							<u-icon v-if="hasChild(data)" name="arrow-right" class="u-icon-wrap u-cell__right-icon-wrap"
								:color="(finalProps.showCheckbox != null && !data[finalProps.showCheckbox] && selectPathId.indexOf(data[finalProps.value]) !== -1) ? '#fa3534' : undefined"
								@click="onSelectContentItem(currentTabData, data)" />
							<u-icon
								v-if="!hasChild(data) && finalProps.showCheckbox != null && !data[finalProps.showCheckbox] && selectPathId.indexOf(data[finalProps.value]) !== -1"
								name="checkbox-mark" class="u-icon-wrap u-cell__right-icon-wrap" color="#fa3534" />
						</view>
					</view>
				</view>
			</view>
		</u-checkbox-group>
	</view>
</template>

<script>
	import style from 'uni.scss';
	import {
		findTreeNodeObjectPath
	} from '@/utils';
	const DEFAULT_PROPS = {
		// 显示名称字段
		text: 'name',
		// 值字段
		value: 'id',
		// 子节点数组字段
		children: 'children',
		// 是否禁用字段
		disabled: 'disabled',
		// 是否叶子节点字段 (如果为空则判断子节点是否为空)
		leaf: undefined,
		// 是否允许选择
		showCheckbox: undefined,
		// 完整数据
		data: undefined
	}
	export default {
		name: 'cascaderSelectPanel',
		props: {
			value: {
				type: [Array, String, Number]
			},
			// 是否禁用
			disabled: {
				type: Boolean,
				default: false
			},
			// 选中颜色
			activeColor: {
				type: String,
				default: style.primary_color
			},
			// 组件高度
			height: {
				type: String
			},
			// 组件数据
			options: {
				type: Array,
				default: () => []
			},
			props: {
				type: Object,
				default: () => {
					return {
						...DEFAULT_PROPS
					}
				}
			},
			// 选项过滤函数
			filter: {
				type: Function
			},
			time: {
				type: Number
			}
		},
		data() {
			return {
				activePanel: 0,
				tabDataList: [],
				checkData: {
					id: new Date().getTime(),
					name: '公司总部',
					checked: false
				}
			}
		},
		methods: {
			isChecked(data) {
				if (data == null) return false;
				if (Array.isArray(this.value)) {
					return this.value.indexOf(data[this.finalProps.value]) !== -1;
				} else {
					return this.value === data[this.finalProps.value];
				}
			},
			onClickNode(data) {
				// 单选
				if (!this.hasChild(data) && this.finalProps.showCheckbox != null && !data[this.finalProps.showCheckbox]) {
					console.log('单选', data);
					this.$emit('input', data[this.finalProps.value]);
					this.$emit('changeCheck', data[this.finalProps.value]);
					if (this.currentTabData) this.tabDataList = this.tabDataList.slice(0, this.currentTabData.index + 1);
				}
			},
			onSelectChange(detail) {
				let {
					value,
					name
				} = detail;
				let temp = Array.isArray(this.value) ? [...this.value] : [];
				if (value) {
					temp.push(name);
				} else {
					temp.splice(temp.indexOf(name), 1);
				}
				this.$emit('input', temp);
				this.$emit('changeCheck', temp);
			},
			changeTab(index) {
				this.activePanel = index
			},
			// 选项是否禁用
			calcItemDisabled(data) {
				if (this.disabled) return true;
				if (data == null) return false;
				if (typeof this.finalProps.disabled === 'function') {
					return this.finalProps.disabled(data);
				} else {
					return this.finalProps.disabled == null ? false : data[this.finalProps.disabled];
				}
			},
			// 是否包含子节点
			hasChild(data) {
				if (this.finalProps.leaf != null && this.finalProps.leaf !== '') return !data[this.finalProps.leaf];
				return Array.isArray(data[this.finalProps.children]) && data[this.finalProps.children].length > 0;
			},
			// Tab页标题
			getTabItemTitle(tabData) {
				let selectDataList = this.getTabSelectDataList(tabData);
				if (!tabData || (selectDataList.length <= 0 && !tabData.value)) {
					return null
				};
				if (tabData.value) {
					return tabData.value[this.finalProps.text]
				};
				let res = selectDataList.map(item => {
					return item[this.finalProps.text];
				}).join(' / ');
				return res
			},
			// 当前Tab页选中数据列表
			getTabSelectDataList(tabData) {
				if (tabData == null) return [];
				let dataList = this.getTabContentList(tabData.index);
				let that = this
				let resList = []
				findTextLoopUp(that.value)

				function findTextLoopUp(valueId) {
					if (valueId) {
						let lastInfo = findTextLoopLast(valueId, dataList)
						if (lastInfo) {
							resList.push(lastInfo)
							findTextLoopUp(lastInfo.parentId)
						}
					}
				}

				function findTextLoopLast(value, list) {
					for (var i = 0; i < list.length; i++) {

						if (value == list[i][that.finalProps.value]) {
							return list[i]
						} else if (list[i][that.finalProps.children] && list[i][that.finalProps.children].length > 0) {
							return findTextLoopLast(value, list[i][that.finalProps.children])
						}
					}
				}
				return resList.reverse()

			},
			// 点击内容项右侧箭头
			onSelectContentItem(tabData, data) {
				if (!this.hasChild(data)) return;
				let oldIndex = this.activePanel;
				// 设置点击项为当前Tab的选中项
				tabData.value = data;
				let tempTime = new Date().getTime();
				// 移除当前Tab页后面所有的Tab页，并且更新当前tab页id（用于刷新当前tab页面）
				this.tabDataList = this.tabDataList.slice(0, tabData.index + 1).map(item => {
					return {
						...item,
						id: item.index === this.activePanel ? tempTime++ : item.id
					}
				});
				// 如果包含子节点，那么添加新Tab页
				if (Array.isArray(data[this.finalProps.children]) && data[this.finalProps.children].length > 0) {
					this.tabDataList.push({
						id: tempTime++,
						index: this.tabDataList.length,
						value: undefined,
						checked: false
					});
					oldIndex++
				}
				this.$nextTick(() => {
					this.activePanel = oldIndex;
				});
			},
			// 获取Tab页下数据列表
			getTabContentList(index) {
				let parentTab = this.tabDataList[index - 1];
				let that = this
				if (!parentTab) {
					let tempList = that.options || [];
					return that.pathNodeCount.filter ? tempList.filter(item => {
						return that.pathNodeCount.filter[item[that.finalProps.value]];
					}) : tempList;
				} else {
					if (parentTab.value != null) {
						let tempList = parentTab.value[that.finalProps.children] || [];
						return that.pathNodeCount.filter ? tempList.filter(item => {
							return that.pathNodeCount.filter[item[that.finalProps.value]];
						}) : tempList;
					} else {
						return [];
					}
				}
			},
			// 初始化Tab页面
			initTabPanel() {
				this.activePanel = 0;
				if (Array.isArray(this.options) && this.options.length > 0) {
					this.tabDataList = [];
					this.tabDataList.push({
						id: new Date().getTime(),
						index: 0,
						value: undefined,
						displayText: '请选择',
						checked: false
					});
				} else {
					this.tabDataList = [];
				}
			},
			// 获取当前节点下有多少项被选中
			getChildSelectCount(data) {
				return data ? this.pathNodeCount.count[data[this.finalProps.value]] : undefined;
			},
			getSelectDataList() {
				if (Array.isArray(this.value)) {
					return this.value.map(item => {
						let path = findTreeNodeObjectPath(this.options, item, this.finalProps.value, this
							.finalProps.children);
						return (Array.isArray(path) && path.length > 0) ? path : null;
					}).filter(item => item != null);
				}
			},
			reset() {
				this.initTabPanel();
			}
		},
		computed: {
			currentTabData() {
				return this.tabDataList[this.activePanel]
			},
			// 根据树形数据以及选中数据计算途经节点命中次数 / 如果有过滤，计算过滤命中的节点以及它的父节点
			pathNodeCount() {
				const self = this;
				let temp = {
					count: {},
					filter: typeof this.filter === 'function' ? {} : undefined
				};

				function findTreeNode(node, idSet, path, idKey, childKey, filter, temp) {
					// 计算选中节点数量
					if (idSet.has(node[idKey])) {
						path.forEach(parent => {
							if (temp) {
								if (temp.count[parent[idKey]] == null) {
									temp.count[parent[idKey]] = 0;
								}
								temp.count[parent[idKey]] = temp.count[parent[idKey]] + 1;
							}
						});
					}

					if (Array.isArray(path)) path.push(node);
					// 计算是过滤后的节点（包括命中节点以及它的父节点）
					if (typeof filter === 'function' && filter.call(self.$parent.$parent, node)) {
						path.forEach(parent => {
							if (temp) {
								if (temp.filter == null) {
									temp.filter = {};
								}
								if (temp.filter[parent[idKey]] == null) {
									temp.filter[parent[idKey]] = true;
								}
							}
						});
					}
					if (node[childKey] != null && Array.isArray(node[childKey])) {
						for (let i = 0; i < node[childKey].length; i++) {
							findTreeNode(node[childKey][i], idSet, path, idKey, childKey, filter, temp);
						}
					}
					if (Array.isArray(path)) path.pop();
				}

				// 添加冗余参数，为了触发变化
				if (Array.isArray(this.value) && Array.isArray(this.options) && self.time >= 0) {
					let path = [];
					let idSet = new Set(this.value);
					this.options.forEach(node => {
						path = [];
						findTreeNode(node, idSet, path, this.finalProps.value, this.finalProps.children, this
							.filter, temp);
					});
					idSet = null;
				}

				return temp;
			},
			selectPath() {
				if (this.value == null || Array.isArray(this.value)) return [];
				return findTreeNodeObjectPath(this.options, this.value, this.finalProps.value, this.finalProps.children);
			},
			selectPathId() {
				return (this.selectPath || []).map(item => item[this.finalProps.value]);
			},
			finalProps() {
				return {
					...DEFAULT_PROPS,
					...this.props
				}
			}
		},
		watch: {
			value: {
				handler() {
					if (this.value == null || (Array.isArray(this.value) && this.value.length === 0)) {
						this.initTabPanel();
					} else {
						this.tabDataList.forEach(item => {
							item.id = (item.value == null && item.index === this.activePanel) ? new Date()
							.getTime() : item.id;
						});
					}
				},
				immediate: true
			},
			options: {
				handler() {
					this.reset();
				},
				immediate: true
			}
		}
	}
</script>

<style lang="scss" scoped>
	// @import '../../static/vkUviewColor/uview.theme.scss';

	.cascader-select-panel {
		width: 100%;
		height: 100%;

		.u-checkbox-group {
			display: block;
			width: 100%;
			height: 100%;
		}

		.tabs {
			position: relative;

			&_wrap {
				height: 96rpx;

				.tabs_nav {
					padding-left: 12rpx !important;
					padding-right: 12rpx !important;
					overflow-x: auto;
					overflow-y: hidden;
					position: relative;
					display: -webkit-box;
					display: -webkit-flex;
					display: flex;
					background-color: #fff;
					-webkit-user-select: none;
					user-select: none;
					height: 100%;
					padding-bottom: 20rpx;
					padding-top: 20rpx;

					.tab {
						position: relative;
						color: #969799;
						font-size: 28rpx;
						line-height: 40rpx;
						cursor: pointer;
						-webkit-box-flex: 0;
						-webkit-flex: none;
						flex: none;
						padding: 0 20rpx;

						&.active {
							color: #323233;
							font-weight: 500;

							.tab-item {
								&::after {
									position: absolute;
									width: 80rpx;
									height: 6rpx;
									left: calc(50% - 40rpx);
									bottom: -20rpx;
									content: ''
								}
							}
						}

						&.unselected {
							color: #969799;
							font-weight: normal;
						}

						&_text {
							.tab-item {
								display: inline-block;
								overflow: hidden;
								text-overflow: ellipsis;
								white-space: nowrap;
								max-width: 30vw;
								min-width: 80rpx;
								text-align: center;
							}
						}
					}
				}
			}

			&_content {
				padding-top: 30rpx;
				border-top: 2rpx solid #F7F7F7;
				height: calc(100% - 128px);
				overflow: auto;

				.tab-content-item {
					flex-shrink: 0;
					width: 100%;
					height: max-content;

					.cell-item {
						display: flex;
						flex-direction: row;
						align-items: center;
						position: relative;
						box-sizing: border-box;
						width: 100%;
						padding: 26rpx 32rpx;
						font-size: 28rpx;
						line-height: 1.5;
						color: #606266;
						background-color: #fff;
						text-align: left;

						.u-cell_title {
							font-size: 28rpx;
						}

						.u-cell__right-icon-wrap {
							margin-left: 10rpx;
							color: #969799;
							font-size: 28rpx;
							display: flex;
							flex-direction: row;
							align-items: center;
							height: 48rpx;
						}

						.u-cell__value {
							overflow: hidden;
							text-align: right;
							/* #ifndef APP-NVUE */
							vertical-align: middle;
							/* #endif */
							color: $u-tips-color;
							font-size: 26rpx;
							flex: 1;
						}
					}
				}
			}
		}
	}
</style>